package com.anlu.base.jdk.jdk8;


import io.micrometer.observation.Observation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class Jdk8NewFeatures {
    private static final Logger logger = LoggerFactory.getLogger(Jdk8NewFeatures.class);
    public static void main(String[] args) {

//        fun1Test();

        test1();



        test2();

        test4();
    }

    static void test1(){
        Integer sumNew = fun(Jdk8NewFeatures::getSum);// 36

        logger.info("sunNew:{}",sumNew);
    }

    static void test2(){
        Date now = new Date();
        Supplier<Long> supplier1 = ()->{return now.getTime();};// Lambda表达式所要实现的getTime()方案，Date类中已经存在getTime()的方案，可以使用方法引用
        System.out.println(supplier1.get());// 1693993605985
        // 对象::实例方法
        Supplier<Long> supplier2 = now::getTime;// 被引用的方法，参数和返回值类型等要和上面supplier1方法体中的实现方法的一样
        System.out.println(supplier2.get());// 1693993605985
    }

    static void test3(){
        Supplier<Long> supplier1 = ()->{return System.currentTimeMillis();};
        System.out.println(supplier1.get());// 1693994527150
        // 类::静态方法
        Supplier<Long> supplier2 = System::currentTimeMillis;
        System.out.println(supplier2.get());// 1693994527151
    }

    static void test4(){
        Function<String,Integer> function1 = (s) -> {
            return s.length();
        };

        System.out.println(function1.apply("hello"));
        // 类::实例方法
        Function<String,Integer> function2 = String::length;
        System.out.println(function2.apply("hello"));// 5
        // 类::实例方法
        BiFunction<String,Integer,String> function3 = String::substring;
        System.out.println(function3.apply("helloworld",5));// world
    }

    static void test5(){
        Supplier<Date> supplier1 = ()->{return new Date();};
        System.out.println(supplier1.get());// Wed Sep 06 18:21:15 CST 2023
        // 类::new
        Supplier<Date> supplier2 = Date::new;
        System.out.println(supplier2.get());// Wed Sep 06 18:21:15 CST 2023
    }

    void test(){
        Operater o = arr -> {
            int sum = 0;
            for (int n : arr) {
                sum += n;
            }
            System.out.println("数组的和为:" + sum);// 36
            return sum;
        };

        Integer sum = fun(o);
        logger.info("sum:{}",sum);


        String res = getFunStr((arr) -> {

            StringBuilder sb = new StringBuilder();
            for(String s : arr){
                sb.append(s);
            }
            return sb.toString();
        });

        logger.info("res = {}",res);
    }



    public static Integer fun(Operater operater) {// 普通方法
        int[] arr = {1, 2, 3,4, 5, 6, 7,8};
        return operater.getSum(arr);
    }

    public static Integer fun1(Function<int[],Integer> function){
        int[] arr = {1, 2, 3,4, 5, 6, 7,8};

        return function.apply(arr);
    }

    static void fun1Test(){
       Integer sunNew = fun1((arr) -> {
           int sum = 0;
           for (int n : arr) {
               sum += n;
           }
           System.out.println("数组的和为:" + sum);// 36
           return sum;
       });
    }

    public static String getFunStr(AnluTest an){
        String[] arr = {"我是","中国人"};
        return an.getString(arr);
    }

    /**
     * 我们知道使用Lambda表达式的前提是需要有函数式接口。
     * 而Lambda使用时不关心接口名，抽象方法名，只关心抽象方法的参数列表和返回值类型。
     * 因此为了让我们使用Lambda方便，JDK提供了大量常用的函数式接口。
     */
    @FunctionalInterface // 函数式接口
    interface Operater {
        // 求数组的和
        public abstract Integer getSum(int[] arr);
    }

    @FunctionalInterface
    interface AnluTest{
        public abstract String getString(String[] arr);

    }

    public static Integer getSum(int[] arr){// 普通方法getSum
        int sum = 0;
        for (int n : arr) {
            sum += n;
        }
        System.out.println("数组的和为:" + sum);// 36
        return sum;
    }

    @FunctionalInterface
    interface ReturnModel<T>{

        public T getModel();

    }




}


